#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include "resource_pool.h"

#define DUMMY_ALLOC_UNINIT	0x01
#define DUMMY_ALLOC_INIT_DONE	0x02
#define DUMMY_FREE_READY	0x04

static void *dummy_alloc(void *pool_data)
{
	unsigned int state = *(unsigned int *)pool_data;

	if (state == DUMMY_ALLOC_UNINIT) {
		return malloc(sizeof(int));
	}
	
	return NULL;
}

static void dummy_free(void *element, void *pool_data)
{
	unsigned int state = *(unsigned int *)pool_data;

	if (state == DUMMY_FREE_READY) {
		free(element);
	}
}

static resource_pool_t *dummy_resource_pool_create(void)
{
#define DUMMY_TEST_POOL_SIZE      1
	resource_pool_t *pool = NULL;
	unsigned int *pool_data = NULL;
	
	pool_data = (unsigned int *)malloc(sizeof(unsigned int));
	if (!pool_data) {
		fprintf(stderr, "malloc pool_data failed.\n");
		return NULL;
	}
	
	*pool_data = DUMMY_ALLOC_UNINIT;
	
	pool = resource_pool_create(DUMMY_TEST_POOL_SIZE, dummy_alloc, dummy_free, pool_data);
	if (!pool) {
		free(pool_data);
		fprintf(stderr, "resource_pool_create failed\n");
		return NULL;
	}

	*(unsigned int *)(pool->pool_data) = DUMMY_ALLOC_INIT_DONE;

	return pool;
}

static void dummy_resource_pool_destroy(resource_pool_t *pool)
{
	*(unsigned int *)pool->pool_data = DUMMY_FREE_READY;
	resource_pool_destroy(pool);
}

struct thread_arg {
	resource_pool_t *pool;
	int thread_seq;
};

static struct thread_arg arg1, arg2, arg3;	

static void *thread_func(void *arg)
{
	unsigned int *e = NULL;

	while (1) {
		printf("th(%d) alloc.\n", ((struct thread_arg *)arg)->thread_seq);
		e = resource_pool_alloc(((struct thread_arg *)arg)->pool);
		sleep(1);
		printf("th(%d) free.\n", ((struct thread_arg *)arg)->thread_seq);
		resource_pool_free(((struct thread_arg *)arg)->pool, e);
		sleep(1);
	}

	return 0;
}

int main(int argc, char *argv[])
{
	pthread_t th1, th2, th3;
	resource_pool_t *pool = NULL;

	pool = dummy_resource_pool_create();
	if (!pool) {
		fprintf(stderr, "dummy pool created failed\n");
	}
	
	arg1.thread_seq = 1;
	arg1.pool = pool;
	pthread_create(&th1, NULL, thread_func, &arg1);
	arg2.thread_seq = 2;
	arg2.pool = pool;
	pthread_create(&th2, NULL, thread_func, &arg2);
	arg3.thread_seq = 3;
	arg3.pool = pool;
	pthread_create(&th3, NULL, thread_func, &arg3);

	pthread_join(th1, NULL);
	pthread_join(th2, NULL);
	pthread_join(th3, NULL);
	
	dummy_resource_pool_destroy(pool);

	return 0;
}
